﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

using PhoneNumber.Classes;

namespace PhoneNumber.Forms
{
    public partial class Form1 : Form
    {
        //爬虫对象容器、bool标志量
        List<Thread> threads=new List<Thread>();
        bool hasStop = true;
        //通过计时器检测已接收到的相关消息数量
        private int countPhoneNumber = 0;
        System.Windows.Forms.Timer timer;
        //已被扫描的url或电话号码
        HashSet<string> tableUrl;
        HashSet<string> tablePhone;
        const int phoneNumberRequired = 100; //一次扫描操作爬取的电话号码数量
        //线程信号量机制和控制停止的标志量
        Semaphore semaphore = new Semaphore(10, 10);
        CancellationTokenSource tokenSource; //每次点击start时动态初始化

        //[Obsolete]
        public Form1()
        {
            InitializeComponent();
            listBoxPhoneNumberScanned.Hide();
            textBoxUrl.Text = "https://www.whu.edu.cn/";
            tableUrl = new HashSet<string>();
            tablePhone = new HashSet<string>();

            timer = new System.Windows.Forms.Timer();
            timer.Interval = 100;
            timer.Tick += judgeIfStop;
            timer.Start();

            this.FormClosed += Form1_FormClosed;
        }

        //[Obsolete]
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            stopThreads();
            Environment.Exit(0);
        }

        /// <summary>
        /// Timer响应函数，当检测到对应状态时停止线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private int count = 0;
        //[Obsolete]
        private void judgeIfStop(Object sender, EventArgs args)
        {
            if (countPhoneNumber >= phoneNumberRequired && !hasStop) 
            {
                hasStop = true;
                stopThreads();
            }
            if (count > 10)
            {
                count = 0;
                for(int i = 0; i < threads.Count; i++)
                {
                    Thread thread = threads[i];
                    if (thread == null || thread.ThreadState == ThreadState.Stopped)
                        threads.Remove(thread);
                }
            }
            count++;
        }

        /// <summary>
        /// 停止所有线程
        /// </summary>
        //[Obsolete]
        private void stopThreads()
        {
            /*            for (int i = 0; i < threads.Count; i++)
                        {
                            Thread thread = threads[i];
                            if (thread != null)
                                try
                                {
                                    thread.Suspend();
                                }
                                catch (Exception) { }
                        }*/
            tokenSource?.Cancel();
            threads.Clear();
        }

        /// <summary>
        /// 菜单选项，可以选择显示已扫描的url或显示扫描得到的电话号码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ToolStripMenuItemShowUrl_Click(object sender, EventArgs e)
        {
            ToolStripMenuItemParent.Text = "选择模式-已扫描的url";
            ToolStripMenuItemShowUrl.Text = "显示已扫描的url √";
            ToolStripMenuItemShowPhone.Text = "显示收集到的电话号码";
            listBoxPhoneNumberScanned.Hide();
            listBoxUrlScanned.Show();
        }

        /// <summary>
        /// 菜单选项，可以选择显示已扫描的url或显示扫描得到的电话号码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ToolStripMenuItemShowPhone_Click(object sender, EventArgs e)
        {
            ToolStripMenuItemParent.Text = "选择模式-收集的电话号码";
            ToolStripMenuItemShowUrl.Text = "显示已扫描的url";
            ToolStripMenuItemShowPhone.Text = "显示收集到的电话号码 √";
            listBoxPhoneNumberScanned.Show();
            listBoxUrlScanned.Hide();
        }

        /// <summary>
        /// 开始按钮的响应函数，将初始化并启动一个新的基础线程，
        /// 若前一个基础线程还在运行，则停止线程，初始化控件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        //[Obsolete]
        private void buttonStart_Click(object sender, EventArgs e)
        {

            if (!hasStop)
                stopThreads();
            tokenSource = new CancellationTokenSource();
            listBoxPhoneNumberScanned.Items.Clear();
            listBoxUrlScanned.Items.Clear();
            tableUrl.Clear();
            tablePhone.Clear();
            hasStop = false;
            countPhoneNumber = 0;
            Thread thread = new Thread(()=>
            {
                //new Crawlers(threads, tableUrl, tablePhone).Scan(textBoxUrl.Text);
                new Crawlers(threads, tableUrl, tablePhone, 
                    semaphore, tokenSource.Token).Scan(textBoxUrl.Text);
            });
            thread.DisableComObjectEagerCleanup();
            threads.Add(thread);
            threads[0].Start();
        }


        #region windows进程通信机制

        private const int WM_COPYDATA = 0x004A; // 自定义消息

        /// <summary>
        /// 接收线程消息，并判断传来的消息是URL还是电话号码，并进行相应处理
        /// </summary>
        /// <param name="m"></param>
        protected override void DefWndProc(ref Message m)
        {
            if (m.Msg == WM_COPYDATA)
            {
                COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
                string message = Marshal.PtrToStringAnsi(cds.lpData);
                if(message.Substring(0,3).Equals("url")) 
                    this.listBoxUrlScanned.Items.Add(message);
                else if(message.Substring(0, 5).Equals("phone"))
                {
                    this.listBoxPhoneNumberScanned.Items.Add(message);
                    countPhoneNumber++;
                }
            }
            base.DefWndProc(ref m);
        }

        #endregion
    }
}



//0x4ea8